package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

// 中间件就是一个HandlerFunc

func indexHandler(context *gin.Context) {
	// gin中间件中使用goroutine
	go aaa(context.Copy()) // 当在中间件或handler中启动新的goroutine时，不能使用原始的上下文（context *gin.Context），必须使用其只读副本（context.Copy()）。
	fmt.Println("index...")
	name, ok := context.Get("name") // 在这个中间件接收值
	if ok {
		fmt.Println(name) // lalala
	}
	context.JSON(http.StatusOK, gin.H{
		"msg": "ok",
	})
}
func aaa(context *gin.Context) {
	lalalaaaa, ok := context.Get("name") // 在这个goroutine调用中，接收传值
	if ok {
		fmt.Println(lalalaaaa) // lalala
	}
}

// 定义中间件
func m1(context *gin.Context) {
	fmt.Println("m1 in ...")
	// 计时
	start := time.Now()
	//context.Next() // 调用后续处理函数，不会先执行下面的代码，会先执行其他中间件函数，其他的中间件函数执行完以后，才会继续执行下面的代码
	//context.Abort() // 阻止调用后续处理的中间件，禁止接着往下执行其他函数，但是下面的本函数的其他代码可以执行完
	cost := time.Since(start)
	fmt.Println("耗时：", cost)
	fmt.Println("m1 out ...")
	context.Set("name", "lalala") // 传值给其他所有要执行的函数，如果上面代码 context.Next() 执行了，这里就会先不执行了
}

func main() {
	//r := gin.Default()
	//gin.Default()默认使用了Logger和Recovery中间件，其中：
	// Logger中间件将日志写入gin.DefaultWriter，即使配置了GIN_MODE=release。
	// Recovery中间件会recover任何panic。如果有panic的话，会写入500响应码。
	// 如果不想使用上面两个默认的中间件，可以使用gin.New()新建一个没有任何默认中间件的路由。
	r := gin.New()

	// 这俩路由接口都使用了 m1 中间件， 可以注册多个中间件，写多个
	r.GET("/shop", m1, func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{"msg": "shop"})
	})
	r.GET("/user", m1, func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{"msg": "user"})
	})

	// r.GET("/index", func(context *gin.Context) {})	// 常规写法
	// GET的参数就是func(context *gin.Context) 类型，所以可以写在外面，然后再传进来，中间件还可以传参
	r.GET("/index", m1, indexHandler) // m1中间件在前面，所以先走m1先打印

	r.Run(":9090")
}
